home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / a_utils / perl / msds-prl / bcdsprl4.zoo / cons.c < prev    next >
C/C++ Source or Header  |  1991-11-28  |  37KB  |  1,517 lines

  1. /* $RCSfile: cons.c,v $$Revision: 4.0.1.2 $$Date: 91/11/05 16:15:13 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    cons.c,v $
  9.  * Revision 4.0.1.2  91/11/05  16:15:13  lwall
  10.  * patch11: debugger got confused over nested subroutine definitions
  11.  * patch11: prepared for ctype implementations that don't define isascii()
  12.  *
  13.  * Revision 4.0.1.1  91/06/07  10:31:15  lwall
  14.  * patch4: new copyright notice
  15.  * patch4: added global modifier for pattern matches
  16.  *
  17.  * Revision 4.0  91/03/20  01:05:51  lwall
  18.  * 4.0 baseline.
  19.  *
  20.  */
  21.  
  22.  
  23. #include "EXTERN.h"
  24. #include "perl.h"
  25. #include "perly.h"
  26.  
  27.  
  28. extern char *tokename[];
  29. extern int yychar;
  30.  
  31.  
  32. static int cmd_tosave();
  33. static int arg_tosave();
  34. static int spat_tosave();
  35.  
  36.  
  37. static bool saw_return;
  38.  
  39.  
  40. SUBR *
  41. make_sub(name,cmd)
  42. char *name;
  43. CMD *cmd;
  44. {
  45.     register SUBR *sub;
  46.     STAB *stab = stabent(name,TRUE);
  47.  
  48.  
  49.     Newz(101,sub,1,SUBR);
  50.     if (stab_sub(stab)) {
  51.     if (dowarn) {
  52.         CMD *oldcurcmd = curcmd;
  53.  
  54.  
  55.         if (cmd)
  56.         curcmd = cmd;
  57.         warn("Subroutine %s redefined",name);
  58.         curcmd = oldcurcmd;
  59.     }
  60.     if (stab_sub(stab)->cmd) {
  61.         cmd_free(stab_sub(stab)->cmd);
  62.         stab_sub(stab)->cmd = Nullcmd;
  63.         afree(stab_sub(stab)->tosave);
  64.     }
  65.     Safefree(stab_sub(stab));
  66.     }
  67.     stab_sub(stab) = sub;
  68.     sub->filestab = curcmd->c_filestab;
  69.     saw_return = FALSE;
  70.     tosave = anew(Nullstab);
  71.     tosave->ary_fill = 0;    /* make 1 based */
  72.     (void)cmd_tosave(cmd,FALSE);    /* this builds the tosave array */
  73.     sub->tosave = tosave;
  74.     if (saw_return) {
  75.     struct compcmd mycompblock;
  76.  
  77.  
  78.     mycompblock.comp_true = cmd;
  79.     mycompblock.comp_alt = Nullcmd;
  80.     cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,Nullarg,mycompblock));
  81.     saw_return = FALSE;
  82.     cmd->c_flags |= CF_TERM;
  83.     }
  84.     sub->cmd = cmd;
  85.     if (perldb) {
  86.     STR *str;
  87.     STR *tmpstr = str_mortal(&str_undef);
  88.  
  89.  
  90.     sprintf(buf,"%s:%ld",stab_val(curcmd->c_filestab)->str_ptr, subline);
  91.     str = str_make(buf,0);
  92.     str_cat(str,"-");
  93.     sprintf(buf,"%ld",(long)curcmd->c_line);
  94.     str_cat(str,buf);
  95.     name = str_get(subname);
  96.     stab_fullname(tmpstr,stab);
  97.     hstore(stab_xhash(DBsub), tmpstr->str_ptr, tmpstr->str_cur, str, 0);
  98.     }
  99.     return sub;
  100. }
  101.  
  102.  
  103. SUBR *
  104. make_usub(name, ix, subaddr, filename)
  105. char *name;
  106. int ix;
  107. int (*subaddr)();
  108. char *filename;
  109. {
  110.     register SUBR *sub;
  111.     STAB *stab = stabent(name,allstabs);
  112.  
  113.  
  114.     if (!stab)                /* unused function */
  115.     return Null(SUBR*);
  116.     Newz(101,sub,1,SUBR);
  117.     if (stab_sub(stab)) {
  118.     if (dowarn)
  119.         warn("Subroutine %s redefined",name);
  120.     if (stab_sub(stab)->cmd) {
  121.         cmd_free(stab_sub(stab)->cmd);
  122.         stab_sub(stab)->cmd = Nullcmd;
  123.         afree(stab_sub(stab)->tosave);
  124.     }
  125.     Safefree(stab_sub(stab));
  126.     }
  127.     stab_sub(stab) = sub;
  128.     sub->filestab = fstab(filename);
  129.     sub->usersub = subaddr;
  130.     sub->userindex = ix;
  131.     return sub;
  132. }
  133.  
  134.  
  135. make_form(stab,fcmd)
  136. STAB *stab;
  137. FCMD *fcmd;
  138. {
  139.     if (stab_form(stab)) {
  140.     FCMD *tmpfcmd;
  141.     FCMD *nextfcmd;
  142.  
  143.  
  144.     for (tmpfcmd = stab_form(stab); tmpfcmd; tmpfcmd = nextfcmd) {
  145.         nextfcmd = tmpfcmd->f_next;
  146.         if (tmpfcmd->f_expr)
  147.         arg_free(tmpfcmd->f_expr);
  148.         if (tmpfcmd->f_unparsed)
  149.         str_free(tmpfcmd->f_unparsed);
  150.         if (tmpfcmd->f_pre)
  151.         Safefree(tmpfcmd->f_pre);
  152.         Safefree(tmpfcmd);
  153.     }
  154.     }
  155.     stab_form(stab) = fcmd;
  156. }
  157.  
  158.  
  159. CMD *
  160. block_head(tail)
  161. register CMD *tail;
  162. {
  163.     CMD *head;
  164.     register int opt;
  165.     register int last_opt = 0;
  166.     register STAB *last_stab = Nullstab;
  167.     register int count = 0;
  168.     register CMD *switchbeg = Nullcmd;
  169.  
  170.  
  171.     if (tail == Nullcmd) {
  172.     return tail;
  173.     }
  174.     head = tail->c_head;
  175.  
  176.  
  177.     for (tail = head; tail; tail = tail->c_next) {
  178.  
  179.  
  180.     /* save one measly dereference at runtime */
  181.     if (tail->c_type == C_IF) {
  182.         if (!(tail->ucmd.ccmd.cc_alt = tail->ucmd.ccmd.cc_alt->c_next))
  183.         tail->c_flags |= CF_TERM;
  184.     }
  185.     else if (tail->c_type == C_EXPR) {
  186.         ARG *arg;
  187.  
  188.  
  189.         if (tail->ucmd.acmd.ac_expr)
  190.         arg = tail->ucmd.acmd.ac_expr;
  191.         else
  192.         arg = tail->c_expr;
  193.         if (arg) {
  194.         if (arg->arg_type == O_RETURN)
  195.             tail->c_flags |= CF_TERM;
  196.         else if (arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  197.             tail->c_flags |= CF_TERM;
  198.         }
  199.     }
  200.     if (!tail->c_next)
  201.         tail->c_flags |= CF_TERM;
  202.  
  203.  
  204.     if (tail->c_expr && (tail->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  205.         opt_arg(tail,1, tail->c_type == C_EXPR);
  206.  
  207.  
  208.     /* now do a little optimization on case-ish structures */
  209.     switch(tail->c_flags & (CF_OPTIMIZE|CF_FIRSTNEG|CF_INVERT)) {
  210.     case CFT_ANCHOR:
  211.         if (stabent("*",FALSE)) {    /* bad assumption here!!! */
  212.         opt = 0;
  213.         break;
  214.         }
  215.         /* FALL THROUGH */
  216.     case CFT_STROP:
  217.         opt = (tail->c_flags & CF_NESURE) ? CFT_STROP : 0;
  218.         break;
  219.     case CFT_CCLASS:
  220.         opt = CFT_STROP;
  221.         break;
  222.     case CFT_NUMOP:
  223.         opt = (tail->c_slen == O_NE ? 0 : CFT_NUMOP);
  224.         if ((tail->c_flags&(CF_NESURE|CF_EQSURE)) != (CF_NESURE|CF_EQSURE))
  225.         opt = 0;
  226.         break;
  227.     default:
  228.         opt = 0;
  229.     }
  230.     if (opt && opt == last_opt && tail->c_stab == last_stab)
  231.         count++;
  232.     else {
  233.         if (count >= 3) {        /* is this the breakeven point? */
  234.         if (last_opt == CFT_NUMOP)
  235.             make_nswitch(switchbeg,count);
  236.         else
  237.             make_cswitch(switchbeg,count);
  238.         }
  239.         if (opt) {
  240.         count = 1;
  241.         switchbeg = tail;
  242.         }
  243.         else
  244.         count = 0;
  245.     }
  246.     last_opt = opt;
  247.     last_stab = tail->c_stab;
  248.     }
  249.     if (count >= 3) {        /* is this the breakeven point? */
  250.     if (last_opt == CFT_NUMOP)
  251.         make_nswitch(switchbeg,count);
  252.     else
  253.         make_cswitch(switchbeg,count);
  254.     }
  255.     return head;
  256. }
  257.  
  258.  
  259. /* We've spotted a sequence of CMDs that all test the value of the same
  260.  * spat.  Thus we can insert a SWITCH in front and jump directly
  261.  * to the correct one.
  262.  */
  263. make_cswitch(head,count)
  264. register CMD *head;
  265. int count;
  266. {
  267.     register CMD *cur;
  268.     register CMD **loc;
  269.     register int i;
  270.     register int min = 255;
  271.     register int max = 0;
  272.  
  273.  
  274.     /* make a new head in the exact same spot */
  275.     New(102,cur, 1, CMD);
  276. #ifdef STRUCTCOPY
  277.     *cur = *head;
  278. #else
  279.     Copy(head,cur,1,CMD);
  280. #endif
  281.     Zero(head,1,CMD);
  282.     head->c_type = C_CSWITCH;
  283.     head->c_next = cur;        /* insert new cmd at front of list */
  284.     head->c_stab = cur->c_stab;
  285.  
  286.  
  287.     Newz(103,loc,258,CMD*);
  288.     loc++;                /* lie a little */
  289.     while (count--) {
  290.     if ((cur->c_flags & CF_OPTIMIZE) == CFT_CCLASS) {
  291.         for (i = 0; i <= 255; i++) {
  292.         if (!loc[i] && cur->c_short->str_ptr[i>>3] & (1 << (i&7))) {
  293.             loc[i] = cur;
  294.             if (i < min)
  295.             min = i;
  296.             if (i > max)
  297.             max = i;
  298.         }
  299.         }
  300.     }
  301.     else {
  302.         i = *cur->c_short->str_ptr & 255;
  303.         if (!loc[i]) {
  304.         loc[i] = cur;
  305.         if (i < min)
  306.             min = i;
  307.         if (i > max)
  308.             max = i;
  309.         }
  310.     }
  311.     cur = cur->c_next;
  312.     }
  313.     max++;
  314.     if (min > 0)
  315.     Copy(&loc[min],&loc[0], max - min, CMD*);
  316.     loc--;
  317.     min--;
  318.     max -= min;
  319.     for (i = 0; i <= max; i++)
  320.     if (!loc[i])
  321.         loc[i] = cur;
  322.     Renew(loc,max+1,CMD*);    /* chop it down to size */
  323.     head->ucmd.scmd.sc_offset = min;
  324.     head->ucmd.scmd.sc_max = max;
  325.     head->ucmd.scmd.sc_next = loc;
  326. }
  327.  
  328.  
  329. make_nswitch(head,count)
  330. register CMD *head;
  331. int count;
  332. {
  333.     register CMD *cur = head;
  334.     register CMD **loc;
  335.     register int i;
  336.     register int min = 32767;
  337.     register int max = -32768;
  338.     int origcount = count;
  339.     double value;        /* or your money back! */
  340.     short changed;        /* so triple your money back! */
  341.  
  342.  
  343.     while (count--) {
  344.     i = (int)str_gnum(cur->c_short);
  345.     value = (double)i;
  346.     if (value != cur->c_short->str_u.str_nval)
  347.         return;        /* fractional values--just forget it */
  348.     changed = i;
  349.     if (changed != i)
  350.         return;        /* too big for a short */
  351.     if (cur->c_slen == O_LE)
  352.         i++;
  353.     else if (cur->c_slen == O_GE)    /* we only do < or > here */
  354.         i--;
  355.     if (i < min)
  356.         min = i;
  357.     if (i > max)
  358.         max = i;
  359.     cur = cur->c_next;
  360.     }
  361.     count = origcount;
  362.     if (max - min > count * 2 + 10)        /* too sparse? */
  363.     return;
  364.  
  365.  
  366.     /* now make a new head in the exact same spot */
  367.     New(104,cur, 1, CMD);
  368. #ifdef STRUCTCOPY
  369.     *cur = *head;
  370. #else
  371.     Copy(head,cur,1,CMD);
  372. #endif
  373.     Zero(head,1,CMD);
  374.     head->c_type = C_NSWITCH;
  375.     head->c_next = cur;        /* insert new cmd at front of list */
  376.     head->c_stab = cur->c_stab;
  377.  
  378.  
  379.     Newz(105,loc, max - min + 3, CMD*);
  380.     loc++;
  381.     max -= min;
  382.     max++;
  383.     while (count--) {
  384.     i = (int)str_gnum(cur->c_short);
  385.     i -= min;
  386.     switch(cur->c_slen) {
  387.     case O_LE:
  388.         i++;
  389.     case O_LT:
  390.         for (i--; i >= -1; i--)
  391.         if (!loc[i])
  392.             loc[i] = cur;
  393.         break;
  394.     case O_GE:
  395.         i--;
  396.     case O_GT:
  397.         for (i++; i <= max; i++)
  398.         if (!loc[i])
  399.             loc[i] = cur;
  400.         break;
  401.     case O_EQ:
  402.         if (!loc[i])
  403.         loc[i] = cur;
  404.         break;
  405.     }
  406.     cur = cur->c_next;
  407.     }
  408.     loc--;
  409.     min--;
  410.     max++;
  411.     for (i = 0; i <= max; i++)
  412.     if (!loc[i])
  413.         loc[i] = cur;
  414.     head->ucmd.scmd.sc_offset = min;
  415.     head->ucmd.scmd.sc_max = max;
  416.     head->ucmd.scmd.sc_next = loc;
  417. }
  418.  
  419.  
  420. CMD *
  421. append_line(head,tail)
  422. register CMD *head;
  423. register CMD *tail;
  424. {
  425.     if (tail == Nullcmd)
  426.     return head;
  427.     if (!tail->c_head)            /* make sure tail is well formed */
  428.     tail->c_head = tail;
  429.     if (head != Nullcmd) {
  430.     tail = tail->c_head;        /* get to start of tail list */
  431.     if (!head->c_head)
  432.         head->c_head = head;    /* start a new head list */
  433.     while (head->c_next) {
  434.         head->c_next->c_head = head->c_head;
  435.         head = head->c_next;    /* get to end of head list */
  436.     }
  437.     head->c_next = tail;        /* link to end of old list */
  438.     tail->c_head = head->c_head;    /* propagate head pointer */
  439.     }
  440.     while (tail->c_next) {
  441.     tail->c_next->c_head = tail->c_head;
  442.     tail = tail->c_next;
  443.     }
  444.     return tail;
  445. }
  446.  
  447.  
  448. CMD *
  449. dodb(cur)
  450. CMD *cur;
  451. {
  452.     register CMD *cmd;
  453.     register CMD *head = cur->c_head;
  454.     STR *str;
  455.  
  456.  
  457.     if (!head)
  458.     head = cur;
  459.     if (!head->c_line)
  460.     return cur;
  461.     str = afetch(stab_xarray(curcmd->c_filestab),(int)head->c_line,FALSE);
  462.     if (str == &str_undef || str->str_nok)
  463.     return cur;
  464.     str->str_u.str_nval = (double)head->c_line;
  465.     str->str_nok = 1;
  466.     Newz(106,cmd,1,CMD);
  467.     str_magic(str, curcmd->c_filestab, 0, Nullch, 0);
  468.     str->str_magic->str_u.str_cmd = cmd;
  469.     cmd->c_type = C_EXPR;
  470.     cmd->ucmd.acmd.ac_stab = Nullstab;
  471.     cmd->ucmd.acmd.ac_expr = Nullarg;
  472.     cmd->c_expr = make_op(O_SUBR, 2,
  473.     stab2arg(A_WORD,DBstab),
  474.     Nullarg,
  475.     Nullarg);
  476.     cmd->c_flags |= CF_COND|CF_DBSUB|CFT_D0;
  477.     cmd->c_line = head->c_line;
  478.     cmd->c_label = head->c_label;
  479.     cmd->c_filestab = curcmd->c_filestab;
  480.     cmd->c_stash = curstash;
  481.     return append_line(cmd, cur);
  482. }
  483.  
  484.  
  485. CMD *
  486. make_acmd(type,stab,cond,arg)
  487. int type;
  488. STAB *stab;
  489. ARG *cond;
  490. ARG *arg;
  491. {
  492.     register CMD *cmd;
  493.  
  494.  
  495.     Newz(107,cmd,1,CMD);
  496.     cmd->c_type = type;
  497.     cmd->ucmd.acmd.ac_stab = stab;
  498.     cmd->ucmd.acmd.ac_expr = arg;
  499.     cmd->c_expr = cond;
  500.     if (cond)
  501.     cmd->c_flags |= CF_COND;
  502.     if (cmdline == NOLINE)
  503.     cmd->c_line = curcmd->c_line;
  504.     else {
  505.     cmd->c_line = cmdline;
  506.     cmdline = NOLINE;
  507.     }
  508.     cmd->c_filestab = curcmd->c_filestab;
  509.     cmd->c_stash = curstash;
  510.     if (perldb)
  511.     cmd = dodb(cmd);
  512.     return cmd;
  513. }
  514.  
  515.  
  516. CMD *
  517. make_ccmd(type,arg,cblock)
  518. int type;
  519. ARG *arg;
  520. struct compcmd cblock;
  521. {
  522.     register CMD *cmd;
  523.  
  524.  
  525.     Newz(108,cmd, 1, CMD);
  526.     cmd->c_type = type;
  527.     cmd->c_expr = arg;
  528.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  529.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  530.     if (arg)
  531.     cmd->c_flags |= CF_COND;
  532.     if (cmdline == NOLINE)
  533.     cmd->c_line = curcmd->c_line;
  534.     else {
  535.     cmd->c_line = cmdline;
  536.     cmdline = NOLINE;
  537.     }
  538.     cmd->c_filestab = curcmd->c_filestab;
  539.     cmd->c_stash = curstash;
  540.     if (perldb)
  541.     cmd = dodb(cmd);
  542.     return cmd;
  543. }
  544.  
  545.  
  546. CMD *
  547. make_icmd(type,arg,cblock)
  548. int type;
  549. ARG *arg;
  550. struct compcmd cblock;
  551. {
  552.     register CMD *cmd;
  553.     register CMD *alt;
  554.     register CMD *cur;
  555.     register CMD *head;
  556.     struct compcmd ncblock;
  557.  
  558.  
  559.     Newz(109,cmd, 1, CMD);
  560.     head = cmd;
  561.     cmd->c_type = type;
  562.     cmd->c_expr = arg;
  563.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  564.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  565.     if (arg)
  566.     cmd->c_flags |= CF_COND;
  567.     if (cmdline == NOLINE)
  568.     cmd->c_line = curcmd->c_line;
  569.     else {
  570.     cmd->c_line = cmdline;
  571.     cmdline = NOLINE;
  572.     }
  573.     cmd->c_filestab = curcmd->c_filestab;
  574.     cmd->c_stash = curstash;
  575.     cur = cmd;
  576.     alt = cblock.comp_alt;
  577.     while (alt && alt->c_type == C_ELSIF) {
  578.     cur = alt;
  579.     alt = alt->ucmd.ccmd.cc_alt;
  580.     }
  581.     if (alt) {            /* a real life ELSE at the end? */
  582.     ncblock.comp_true = alt;
  583.     ncblock.comp_alt = Nullcmd;
  584.     alt = append_line(cur,make_ccmd(C_ELSE,Nullarg,ncblock));
  585.     cur->ucmd.ccmd.cc_alt = alt;
  586.     }
  587.     else
  588.     alt = cur;        /* no ELSE, so cur is proxy ELSE */
  589.  
  590.  
  591.     cur = cmd;
  592.     while (cmd) {        /* now point everyone at the ELSE */
  593.     cur = cmd;
  594.     cmd = cur->ucmd.ccmd.cc_alt;
  595.     cur->c_head = head;
  596.     if (cur->c_type == C_ELSIF)
  597.         cur->c_type = C_IF;
  598.     if (cur->c_type == C_IF)
  599.         cur->ucmd.ccmd.cc_alt = alt;
  600.     if (cur == alt)
  601.         break;
  602.     cur->c_next = cmd;
  603.     }
  604.     if (perldb)
  605.     cur = dodb(cur);
  606.     return cur;
  607. }
  608.  
  609.  
  610. void
  611. opt_arg(cmd,fliporflop,acmd)
  612. register CMD *cmd;
  613. int fliporflop;
  614. int acmd;
  615. {
  616.     register ARG *arg;
  617.     int opt = CFT_EVAL;
  618.     int sure = 0;
  619.     ARG *arg2;
  620.     int context = 0;    /* 0 = normal, 1 = before &&, 2 = before || */
  621.     int flp = fliporflop;
  622.  
  623.  
  624.     if (!cmd)
  625.     return;
  626.     if (!(arg = cmd->c_expr)) {
  627.     cmd->c_flags &= ~CF_COND;
  628.     return;
  629.     }
  630.  
  631.  
  632.     /* Can we turn && and || into if and unless? */
  633.  
  634.  
  635.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM) &&
  636.       (arg->arg_type == O_AND || arg->arg_type == O_OR) ) {
  637.     dehoist(arg,1);
  638.     arg[2].arg_type &= A_MASK;    /* don't suppress eval */
  639.     dehoist(arg,2);
  640.     cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg;
  641.     cmd->c_expr = arg[1].arg_ptr.arg_arg;
  642.     if (arg->arg_type == O_OR)
  643.         cmd->c_flags ^= CF_INVERT;        /* || is like unless */
  644.     arg->arg_len = 0;
  645.     free_arg(arg);
  646.     arg = cmd->c_expr;
  647.     }
  648.  
  649.  
  650.     /* Turn "if (!expr)" into "unless (expr)" */
  651.  
  652.  
  653.     if (!(cmd->c_flags & CF_TERM)) {        /* unless return value wanted */
  654.     while (arg->arg_type == O_NOT) {
  655.         dehoist(arg,1);
  656.         cmd->c_flags ^= CF_INVERT;        /* flip sense of cmd */
  657.         cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */
  658.         free_arg(arg);
  659.         arg = cmd->c_expr;            /* here we go again */
  660.     }
  661.     }
  662.  
  663.  
  664.     if (!arg->arg_len) {        /* sanity check */
  665.     cmd->c_flags |= opt;
  666.     return;
  667.     }
  668.  
  669.  
  670.     /* for "cond .. cond" we set up for the initial check */
  671.  
  672.  
  673.     if (arg->arg_type == O_FLIP)
  674.     context |= 4;
  675.  
  676.  
  677.     /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */
  678.  
  679.  
  680.   morecontext:
  681.     if (arg->arg_type == O_AND)
  682.     context |= 1;
  683.     else if (arg->arg_type == O_OR)
  684.     context |= 2;
  685.     if (context && (arg[flp].arg_type & A_MASK) == A_EXPR) {
  686.     arg = arg[flp].arg_ptr.arg_arg;
  687.     flp = 1;
  688.     if (arg->arg_type == O_AND || arg->arg_type == O_OR)
  689.         goto morecontext;
  690.     }
  691.     if ((context & 3) == 3)
  692.     return;
  693.  
  694.  
  695.     if (arg[flp].arg_flags & (AF_PRE|AF_POST)) {
  696.     cmd->c_flags |= opt;
  697.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM)
  698.       && cmd->c_expr->arg_type == O_ITEM) {
  699.         arg[flp].arg_flags &= ~AF_POST;    /* prefer ++$foo to $foo++ */
  700.         arg[flp].arg_flags |= AF_PRE;    /*  if value not wanted */
  701.     }
  702.     return;                /* side effect, can't optimize */
  703.     }
  704.  
  705.  
  706.     if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP ||
  707.       arg->arg_type == O_AND || arg->arg_type == O_OR) {
  708.     if ((arg[flp].arg_type & A_MASK) == A_SINGLE) {
  709.         opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE);
  710.         cmd->c_short = str_smake(arg[flp].arg_ptr.arg_str);
  711.         goto literal;
  712.     }
  713.     else if ((arg[flp].arg_type & A_MASK) == A_STAB ||
  714.       (arg[flp].arg_type & A_MASK) == A_LVAL) {
  715.         cmd->c_stab  = arg[flp].arg_ptr.arg_stab;
  716.         if (!context)
  717.         arg[flp].arg_ptr.arg_stab = Nullstab;
  718.         opt = CFT_REG;
  719.       literal:
  720.         if (!context) {    /* no && or ||? */
  721.         arg_free(arg);
  722.         cmd->c_expr = Nullarg;
  723.         }
  724.         if (!(context & 1))
  725.         cmd->c_flags |= CF_EQSURE;
  726.         if (!(context & 2))
  727.         cmd->c_flags |= CF_NESURE;
  728.     }
  729.     }
  730.     else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST ||
  731.          arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) {
  732.     if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  733.         (arg[2].arg_type & A_MASK) == A_SPAT &&
  734.         arg[2].arg_ptr.arg_spat->spat_short &&
  735.         (arg->arg_type == O_SUBST || arg->arg_type == O_NSUBST ||
  736.          (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_GLOBAL) == 0 )) {
  737.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  738.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_spat->spat_short);
  739.         cmd->c_slen  = arg[2].arg_ptr.arg_spat->spat_slen;
  740.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL &&
  741.         !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) &&
  742.         (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) )
  743.         sure |= CF_EQSURE;        /* (SUBST must be forced even */
  744.                         /* if we know it will work.) */
  745.         if (arg->arg_type != O_SUBST) {
  746.         arg[2].arg_ptr.arg_spat->spat_short = Nullstr;
  747.         arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */
  748.         }
  749.         sure |= CF_NESURE;        /* normally only sure if it fails */
  750.         if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST)
  751.         cmd->c_flags |= CF_FIRSTNEG;
  752.         if (context & 1) {        /* only sure if thing is false */
  753.         if (cmd->c_flags & CF_FIRSTNEG)
  754.             sure &= ~CF_NESURE;
  755.         else
  756.             sure &= ~CF_EQSURE;
  757.         }
  758.         else if (context & 2) {    /* only sure if thing is true */
  759.         if (cmd->c_flags & CF_FIRSTNEG)
  760.             sure &= ~CF_EQSURE;
  761.         else
  762.             sure &= ~CF_NESURE;
  763.         }
  764.         if (sure & (CF_EQSURE|CF_NESURE)) {    /* if we know anything*/
  765.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST)
  766.             opt = CFT_SCAN;
  767.         else
  768.             opt = CFT_ANCHOR;
  769.         if (sure == (CF_EQSURE|CF_NESURE)    /* really sure? */
  770.             && arg->arg_type == O_MATCH
  771.             && context & 4
  772.             && fliporflop == 1) {
  773.             spat_free(arg[2].arg_ptr.arg_spat);
  774.             arg[2].arg_ptr.arg_spat = Nullspat;    /* don't do twice */
  775.         }
  776.         else
  777.             cmd->c_spat = arg[2].arg_ptr.arg_spat;
  778.         cmd->c_flags |= sure;
  779.         }
  780.     }
  781.     }
  782.     else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE ||
  783.          arg->arg_type == O_SLT || arg->arg_type == O_SGT) {
  784.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  785.         if (arg[2].arg_type == A_SINGLE) {
  786.         /*SUPPRESS 594*/
  787.         char *junk = str_get(arg[2].arg_ptr.arg_str);
  788.  
  789.  
  790.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  791.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_str);
  792.         cmd->c_slen  = cmd->c_short->str_cur+1;
  793.         switch (arg->arg_type) {
  794.         case O_SLT: case O_SGT:
  795.             sure |= CF_EQSURE;
  796.             cmd->c_flags |= CF_FIRSTNEG;
  797.             break;
  798.         case O_SNE:
  799.             cmd->c_flags |= CF_FIRSTNEG;
  800.             /* FALL THROUGH */
  801.         case O_SEQ:
  802.             sure |= CF_NESURE|CF_EQSURE;
  803.             break;
  804.         }
  805.         if (context & 1) {    /* only sure if thing is false */
  806.             if (cmd->c_flags & CF_FIRSTNEG)
  807.             sure &= ~CF_NESURE;
  808.             else
  809.             sure &= ~CF_EQSURE;
  810.         }
  811.         else if (context & 2) { /* only sure if thing is true */
  812.             if (cmd->c_flags & CF_FIRSTNEG)
  813.             sure &= ~CF_EQSURE;
  814.             else
  815.             sure &= ~CF_NESURE;
  816.         }
  817.         if (sure & (CF_EQSURE|CF_NESURE)) {
  818.             opt = CFT_STROP;
  819.             cmd->c_flags |= sure;
  820.         }
  821.         }
  822.     }
  823.     }
  824.     else if (arg->arg_type == O_EQ || arg->arg_type == O_NE ||
  825.          arg->arg_type == O_LE || arg->arg_type == O_GE ||
  826.          arg->arg_type == O_LT || arg->arg_type == O_GT) {
  827.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  828.         if (arg[2].arg_type == A_SINGLE) {
  829.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  830.         if (dowarn) {
  831.             STR *str = arg[2].arg_ptr.arg_str;
  832.  
  833.  
  834.             if ((!str->str_nok && !looks_like_number(str)))
  835.             warn("Possible use of == on string value");
  836.         }
  837.         cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str));
  838.         cmd->c_slen = arg->arg_type;
  839.         sure |= CF_NESURE|CF_EQSURE;
  840.         if (context & 1) {    /* only sure if thing is false */
  841.             sure &= ~CF_EQSURE;
  842.         }
  843.         else if (context & 2) { /* only sure if thing is true */
  844.             sure &= ~CF_NESURE;
  845.         }
  846.         if (sure & (CF_EQSURE|CF_NESURE)) {
  847.             opt = CFT_NUMOP;
  848.             cmd->c_flags |= sure;
  849.         }
  850.         }
  851.     }
  852.     }
  853.     else if (arg->arg_type == O_ASSIGN &&
  854.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  855.          arg[1].arg_ptr.arg_stab == defstab &&
  856.          arg[2].arg_type == A_EXPR ) {
  857.     arg2 = arg[2].arg_ptr.arg_arg;
  858.     if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) {
  859.         opt = CFT_GETS;
  860.         cmd->c_stab = arg2[1].arg_ptr.arg_stab;
  861.         if (!(stab_io(arg2[1].arg_ptr.arg_stab)->flags & IOF_ARGV)) {
  862.         free_arg(arg2);
  863.         arg[2].arg_ptr.arg_arg = Nullarg;
  864.         free_arg(arg);
  865.         cmd->c_expr = Nullarg;
  866.         }
  867.     }
  868.     }
  869.     else if (arg->arg_type == O_CHOP &&
  870.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) {
  871.     opt = CFT_CHOP;
  872.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  873.     free_arg(arg);
  874.     cmd->c_expr = Nullarg;
  875.     }
  876.     if (context & 4)
  877.     opt |= CF_FLIP;
  878.     cmd->c_flags |= opt;
  879.  
  880.  
  881.     if (cmd->c_flags & CF_FLIP) {
  882.     if (fliporflop == 1) {
  883.         arg = cmd->c_expr;    /* get back to O_FLIP arg */
  884.         New(110,arg[3].arg_ptr.arg_cmd, 1, CMD);
  885.         Copy(cmd, arg[3].arg_ptr.arg_cmd, 1, CMD);
  886.         New(111,arg[4].arg_ptr.arg_cmd,1,CMD);
  887.         Copy(cmd, arg[4].arg_ptr.arg_cmd, 1, CMD);
  888.         opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd);
  889.         arg->arg_len = 2;        /* this is a lie */
  890.     }
  891.     else {
  892.         if ((opt & CF_OPTIMIZE) == CFT_EVAL)
  893.         cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP;
  894.     }
  895.     }
  896. }
  897.  
  898.  
  899. CMD *
  900. add_label(lbl,cmd)
  901. char *lbl;
  902. register CMD *cmd;
  903. {
  904.     if (cmd)
  905.     cmd->c_label = lbl;
  906.     return cmd;
  907. }
  908.  
  909.  
  910. CMD *
  911. addcond(cmd, arg)
  912. register CMD *cmd;
  913. register ARG *arg;
  914. {
  915.     cmd->c_expr = arg;
  916.     cmd->c_flags |= CF_COND;
  917.     return cmd;
  918. }
  919.  
  920.  
  921. CMD *
  922. addloop(cmd, arg)
  923. register CMD *cmd;
  924. register ARG *arg;
  925. {
  926.     void while_io();
  927.  
  928.  
  929.     cmd->c_expr = arg;
  930.     cmd->c_flags |= CF_COND|CF_LOOP;
  931.  
  932.  
  933.     if (!(cmd->c_flags & CF_INVERT))
  934.     while_io(cmd);        /* add $_ =, if necessary */
  935.  
  936.  
  937.     if (cmd->c_type == C_BLOCK)
  938.     cmd->c_flags &= ~CF_COND;
  939.     else {
  940.     arg = cmd->ucmd.acmd.ac_expr;
  941.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  942.         cmd->c_flags &= ~CF_COND;  /* "do {} while" happens at least once */
  943.     if (arg && (arg->arg_flags & AF_DEPR) &&
  944.       (arg->arg_type == O_SUBR || arg->arg_type == O_DBSUBR) )
  945.         cmd->c_flags &= ~CF_COND;  /* likewise for "do subr() while" */
  946.     }
  947.     return cmd;
  948. }
  949.  
  950.  
  951. CMD *
  952. invert(cmd)
  953. CMD *cmd;
  954. {
  955.     register CMD *targ = cmd;
  956.     if (targ->c_head)
  957.     targ = targ->c_head;
  958.     if (targ->c_flags & CF_DBSUB)
  959.     targ = targ->c_next;
  960.     targ->c_flags ^= CF_INVERT;
  961.     return cmd;
  962. }
  963.  
  964.  
  965. yyerror(s)
  966. char *s;
  967. {
  968.     char tmpbuf[258];
  969.     char tmp2buf[258];
  970.     char *tname = tmpbuf;
  971.  
  972.  
  973.     if (bufptr > oldoldbufptr && bufptr - oldoldbufptr < 200 &&
  974.       oldoldbufptr != oldbufptr && oldbufptr != bufptr) {
  975.     while (isSPACE(*oldoldbufptr))
  976.         oldoldbufptr++;
  977.     strncpy(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr);
  978.     tmp2buf[bufptr - oldoldbufptr] = '\0';
  979.     sprintf(tname,"next 2 tokens \"%s\"",tmp2buf);
  980.     }
  981.     else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 &&
  982.       oldbufptr != bufptr) {
  983.     while (isSPACE(*oldbufptr))
  984.         oldbufptr++;
  985.     strncpy(tmp2buf, oldbufptr, bufptr - oldbufptr);
  986.     tmp2buf[bufptr - oldbufptr] = '\0';
  987.     sprintf(tname,"next token \"%s\"",tmp2buf);
  988.     }
  989.     else if (yychar > 256)
  990.     tname = "next token ???";
  991.     else if (!yychar)
  992.     (void)strcpy(tname,"at EOF");
  993.     else if (yychar < 32)
  994.     (void)sprintf(tname,"next char ^%c",yychar+64);
  995.     else if (yychar == 127)
  996.     (void)strcpy(tname,"at EOF");
  997.     else
  998.     (void)sprintf(tname,"next char %c",yychar);
  999.     (void)sprintf(buf, "%s in file %s at line %d, %s\n",
  1000.       s,stab_val(curcmd->c_filestab)->str_ptr,curcmd->c_line,tname);
  1001.     if (curcmd->c_line == multi_end && multi_start < multi_end)
  1002.     sprintf(buf+strlen(buf),
  1003.       "  (Might be a runaway multi-line %c%c string starting on line %d)\n",
  1004.       multi_open,multi_close,multi_start);
  1005.     if (in_eval)
  1006.     str_cat(stab_val(stabent("@",TRUE)),buf);
  1007.     else
  1008.     fputs(buf,stderr);
  1009.     if (++error_count >= 10)
  1010.     fatal("%s has too many errors.\n",
  1011.     stab_val(curcmd->c_filestab)->str_ptr);
  1012. }
  1013.  
  1014.  
  1015. void
  1016. while_io(cmd)
  1017. register CMD *cmd;
  1018. {
  1019.     register ARG *arg = cmd->c_expr;
  1020.     STAB *asgnstab;
  1021.  
  1022.  
  1023.     /* hoist "while (<channel>)" up into command block */
  1024.  
  1025.  
  1026.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) {
  1027.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1028.     cmd->c_flags |= CFT_GETS;    /* and set it to do the input */
  1029.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  1030.     if (stab_io(arg[1].arg_ptr.arg_stab)->flags & IOF_ARGV) {
  1031.         cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$_ =" */
  1032.            stab2arg(A_LVAL,defstab), arg, Nullarg));
  1033.     }
  1034.     else {
  1035.         free_arg(arg);
  1036.         cmd->c_expr = Nullarg;
  1037.     }
  1038.     }
  1039.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) {
  1040.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1041.     cmd->c_flags |= CFT_INDGETS;    /* and set it to do the input */
  1042.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  1043.     free_arg(arg);
  1044.     cmd->c_expr = Nullarg;
  1045.     }
  1046.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) {
  1047.     if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY)
  1048.         asgnstab = cmd->c_stab;
  1049.     else
  1050.         asgnstab = defstab;
  1051.     cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$foo =" */
  1052.        stab2arg(A_LVAL,asgnstab), arg, Nullarg));
  1053.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1054.     }
  1055. }
  1056.  
  1057.  
  1058. CMD *
  1059. wopt(cmd)
  1060. register CMD *cmd;
  1061. {
  1062.     register CMD *tail;
  1063.     CMD *newtail;
  1064.     register int i;
  1065.  
  1066.  
  1067.     if (cmd->c_expr && (cmd->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  1068.     opt_arg(cmd,1, cmd->c_type == C_EXPR);
  1069.  
  1070.  
  1071.     while_io(cmd);        /* add $_ =, if necessary */
  1072.  
  1073.  
  1074.     /* First find the end of the true list */
  1075.  
  1076.  
  1077.     tail = cmd->ucmd.ccmd.cc_true;
  1078.     if (tail == Nullcmd)
  1079.     return cmd;
  1080.     New(112,newtail, 1, CMD);    /* guaranteed continue */
  1081.     for (;;) {
  1082.     /* optimize "next" to point directly to continue block */
  1083.     if (tail->c_type == C_EXPR &&
  1084.         tail->ucmd.acmd.ac_expr &&
  1085.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1086.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1087.          (cmd->c_label &&
  1088.           strEQ(cmd->c_label,
  1089.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1090.     {
  1091.         arg_free(tail->ucmd.acmd.ac_expr);
  1092.         tail->ucmd.acmd.ac_expr = Nullarg;
  1093.         tail->c_type = C_NEXT;
  1094.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1095.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1096.         else
  1097.         tail->ucmd.ccmd.cc_alt = newtail;
  1098.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1099.     }
  1100.     else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1101.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1102.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1103.         else
  1104.         tail->ucmd.ccmd.cc_alt = newtail;
  1105.     }
  1106.     else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1107.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1108.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1109.             if (!tail->ucmd.scmd.sc_next[i])
  1110.             tail->ucmd.scmd.sc_next[i] = cmd->ucmd.ccmd.cc_alt;
  1111.         }
  1112.         else {
  1113.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1114.             if (!tail->ucmd.scmd.sc_next[i])
  1115.             tail->ucmd.scmd.sc_next[i] = newtail;
  1116.         }
  1117.     }
  1118.  
  1119.  
  1120.     if (!tail->c_next)
  1121.         break;
  1122.     tail = tail->c_next;
  1123.     }
  1124.  
  1125.  
  1126.     /* if there's a continue block, link it to true block and find end */
  1127.  
  1128.  
  1129.     if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1130.     tail->c_next = cmd->ucmd.ccmd.cc_alt;
  1131.     tail = tail->c_next;
  1132.     for (;;) {
  1133.         /* optimize "next" to point directly to continue block */
  1134.         if (tail->c_type == C_EXPR &&
  1135.         tail->ucmd.acmd.ac_expr &&
  1136.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1137.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1138.          (cmd->c_label &&
  1139.           strEQ(cmd->c_label,
  1140.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1141.         {
  1142.         arg_free(tail->ucmd.acmd.ac_expr);
  1143.         tail->ucmd.acmd.ac_expr = Nullarg;
  1144.         tail->c_type = C_NEXT;
  1145.         tail->ucmd.ccmd.cc_alt = newtail;
  1146.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1147.         }
  1148.         else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1149.         tail->ucmd.ccmd.cc_alt = newtail;
  1150.         }
  1151.         else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1152.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1153.             if (!tail->ucmd.scmd.sc_next[i])
  1154.             tail->ucmd.scmd.sc_next[i] = newtail;
  1155.         }
  1156.  
  1157.  
  1158.         if (!tail->c_next)
  1159.         break;
  1160.         tail = tail->c_next;
  1161.     }
  1162.     /*SUPPRESS 530*/
  1163.     for ( ; tail->c_next; tail = tail->c_next) ;
  1164.     }
  1165.  
  1166.  
  1167.     /* Here's the real trick: link the end of the list back to the beginning,
  1168.      * inserting a "last" block to break out of the loop.  This saves one or
  1169.      * two procedure calls every time through the loop, because of how cmd_exec
  1170.      * does tail recursion.
  1171.      */
  1172.  
  1173.  
  1174.     tail->c_next = newtail;
  1175.     tail = newtail;
  1176.     if (!cmd->ucmd.ccmd.cc_alt)
  1177.     cmd->ucmd.ccmd.cc_alt = tail;    /* every loop has a continue now */
  1178.  
  1179.  
  1180. #ifndef lint
  1181.     (void)bcopy((char *)cmd, (char *)tail, sizeof(CMD));
  1182. #endif
  1183.     tail->c_type = C_EXPR;
  1184.     tail->c_flags ^= CF_INVERT;        /* turn into "last unless" */
  1185.     tail->c_next = tail->ucmd.ccmd.cc_true;    /* loop directly back to top */
  1186.     tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg);
  1187.     tail->ucmd.acmd.ac_stab = Nullstab;
  1188.     return cmd;
  1189. }
  1190.  
  1191.  
  1192. CMD *
  1193. over(eachstab,cmd)
  1194. STAB *eachstab;
  1195. register CMD *cmd;
  1196. {
  1197.     /* hoist "for $foo (@bar)" up into command block */
  1198.  
  1199.  
  1200.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1201.     cmd->c_flags |= CFT_ARRAY;        /* and set it to do the iteration */
  1202.     cmd->c_stab = eachstab;
  1203.     cmd->c_short = Str_new(23,0);    /* just to save a field in struct cmd */
  1204.     cmd->c_short->str_u.str_useful = -1;
  1205.  
  1206.  
  1207.     return cmd;
  1208. }
  1209.  
  1210.  
  1211. cmd_free(cmd)
  1212. register CMD *cmd;
  1213. {
  1214.     register CMD *tofree;
  1215.     register CMD *head = cmd;
  1216.  
  1217.  
  1218.     while (cmd) {
  1219.     if (cmd->c_type != C_WHILE) {    /* WHILE block is duplicated */
  1220.         if (cmd->c_label) {
  1221.         Safefree(cmd->c_label);
  1222.         cmd->c_label = Nullch;
  1223.         }
  1224.         if (cmd->c_short) {
  1225.         str_free(cmd->c_short);
  1226.         cmd->c_short = Nullstr;
  1227.         }
  1228.         if (cmd->c_expr) {
  1229.         arg_free(cmd->c_expr);
  1230.         cmd->c_expr = Nullarg;
  1231.         }
  1232.     }
  1233.     switch (cmd->c_type) {
  1234.     case C_WHILE:
  1235.     case C_BLOCK:
  1236.     case C_ELSE:
  1237.     case C_IF:
  1238.         if (cmd->ucmd.ccmd.cc_true) {
  1239.         cmd_free(cmd->ucmd.ccmd.cc_true);
  1240.         cmd->ucmd.ccmd.cc_true = Nullcmd;
  1241.         }
  1242.         break;
  1243.     case C_EXPR:
  1244.         if (cmd->ucmd.acmd.ac_expr) {
  1245.         arg_free(cmd->ucmd.acmd.ac_expr);
  1246.         cmd->ucmd.acmd.ac_expr = Nullarg;
  1247.         }
  1248.         break;
  1249.     }
  1250.     tofree = cmd;
  1251.     cmd = cmd->c_next;
  1252.     if (tofree != head)        /* to get Saber to shut up */
  1253.         Safefree(tofree);
  1254.     if (cmd && cmd == head)        /* reached end of while loop */
  1255.         break;
  1256.     }
  1257.     Safefree(head);
  1258. }
  1259.  
  1260.  
  1261. arg_free(arg)
  1262. register ARG *arg;
  1263. {
  1264.     register int i;
  1265.  
  1266.  
  1267.     for (i = 1; i <= arg->arg_len; i++) {
  1268.     switch (arg[i].arg_type & A_MASK) {
  1269.     case A_NULL:
  1270.         if (arg->arg_type == O_TRANS) {
  1271.         Safefree(arg[i].arg_ptr.arg_cval);
  1272.         arg[i].arg_ptr.arg_cval = Nullch;
  1273.         }
  1274.         break;
  1275.     case A_LEXPR:
  1276.         if (arg->arg_type == O_AASSIGN &&
  1277.           arg[i].arg_ptr.arg_arg->arg_type == O_LARRAY) {
  1278.         char *name =
  1279.           stab_name(arg[i].arg_ptr.arg_arg[1].arg_ptr.arg_stab);
  1280.  
  1281.  
  1282.         if (strnEQ("_GEN_",name, 5))    /* array for foreach */
  1283.             hdelete(defstash,name,strlen(name));
  1284.         }
  1285.         /* FALL THROUGH */
  1286.     case A_EXPR:
  1287.         arg_free(arg[i].arg_ptr.arg_arg);
  1288.         arg[i].arg_ptr.arg_arg = Nullarg;
  1289.         break;
  1290.     case A_CMD:
  1291.         cmd_free(arg[i].arg_ptr.arg_cmd);
  1292.         arg[i].arg_ptr.arg_cmd = Nullcmd;
  1293.         break;
  1294.     case A_WORD:
  1295.     case A_STAB:
  1296.     case A_LVAL:
  1297.     case A_READ:
  1298.     case A_GLOB:
  1299.     case A_ARYLEN:
  1300.     case A_LARYLEN:
  1301.     case A_ARYSTAB:
  1302.     case A_LARYSTAB:
  1303.         break;
  1304.     case A_SINGLE:
  1305.     case A_DOUBLE:
  1306.     case A_BACKTICK:
  1307.         str_free(arg[i].arg_ptr.arg_str);
  1308.         arg[i].arg_ptr.arg_str = Nullstr;
  1309.         break;
  1310.     case A_SPAT:
  1311.         spat_free(arg[i].arg_ptr.arg_spat);
  1312.         arg[i].arg_ptr.arg_spat = Nullspat;
  1313.         break;
  1314.     }
  1315.     }
  1316.     free_arg(arg);
  1317. }
  1318.  
  1319.  
  1320. spat_free(spat)
  1321. register SPAT *spat;
  1322. {
  1323.     register SPAT *sp;
  1324.     HENT *entry;
  1325.  
  1326.  
  1327.     if (spat->spat_runtime) {
  1328.     arg_free(spat->spat_runtime);
  1329.     spat->spat_runtime = Nullarg;
  1330.     }
  1331.     if (spat->spat_repl) {
  1332.     arg_free(spat->spat_repl);
  1333.     spat->spat_repl = Nullarg;
  1334.     }
  1335.     if (spat->spat_short) {
  1336.     str_free(spat->spat_short);
  1337.     spat->spat_short = Nullstr;
  1338.     }
  1339.     if (spat->spat_regexp) {
  1340.     regfree(spat->spat_regexp);
  1341.     spat->spat_regexp = Null(REGEXP*);
  1342.     }
  1343.  
  1344.  
  1345.     /* now unlink from spat list */
  1346.  
  1347.  
  1348.     for (entry = defstash->tbl_array['_']; entry; entry = entry->hent_next) {
  1349.     register HASH *stash;
  1350.     STAB *stab = (STAB*)entry->hent_val;
  1351.  
  1352.  
  1353.     if (!stab)
  1354.         continue;
  1355.     stash = stab_hash(stab);
  1356.     if (!stash || stash->tbl_spatroot == Null(SPAT*))
  1357.         continue;
  1358.     if (stash->tbl_spatroot == spat)
  1359.         stash->tbl_spatroot = spat->spat_next;
  1360.     else {
  1361.         for (sp = stash->tbl_spatroot;
  1362.           sp && sp->spat_next != spat;
  1363.           sp = sp->spat_next)
  1364.         /*SUPPRESS 530*/
  1365.         ;
  1366.         if (sp)
  1367.         sp->spat_next = spat->spat_next;
  1368.     }
  1369.     }
  1370.     Safefree(spat);
  1371. }
  1372.  
  1373.  
  1374. /* Recursively descend a command sequence and push the address of any string
  1375.  * that needs saving on recursion onto the tosave array.
  1376.  */
  1377.  
  1378.  
  1379. static int
  1380. cmd_tosave(cmd,willsave)
  1381. register CMD *cmd;
  1382. int willsave;                /* willsave passes down the tree */
  1383. {
  1384.     register CMD *head = cmd;
  1385.     int shouldsave = FALSE;        /* shouldsave passes up the tree */
  1386.     int tmpsave;
  1387.     register CMD *lastcmd = Nullcmd;
  1388.  
  1389.  
  1390.     while (cmd) {
  1391.     if (cmd->c_expr)
  1392.         shouldsave |= arg_tosave(cmd->c_expr,willsave);
  1393.     switch (cmd->c_type) {
  1394.     case C_WHILE:
  1395.         if (cmd->ucmd.ccmd.cc_true) {
  1396.         tmpsave = cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1397.  
  1398.  
  1399.         /* Here we check to see if the temporary array generated for
  1400.          * a foreach needs to be localized because of recursion.
  1401.          */
  1402.         if (tmpsave && (cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) {
  1403.             if (lastcmd &&
  1404.               lastcmd->c_type == C_EXPR &&
  1405.               lastcmd->c_expr) {
  1406.             ARG *arg = lastcmd->c_expr;
  1407.  
  1408.  
  1409.             if (arg->arg_type == O_ASSIGN &&
  1410.                 arg[1].arg_type == A_LEXPR &&
  1411.                 arg[1].arg_ptr.arg_arg->arg_type == O_LARRAY &&
  1412.                 strnEQ("_GEN_",
  1413.                   stab_name(
  1414.                 arg[1].arg_ptr.arg_arg[1].arg_ptr.arg_stab),
  1415.                   5)) {    /* array generated for foreach */
  1416.                 (void)localize(arg);
  1417.             }
  1418.             }
  1419.  
  1420.  
  1421.             /* in any event, save the iterator */
  1422.  
  1423.  
  1424.             (void)apush(tosave,cmd->c_short);
  1425.         }
  1426.         shouldsave |= tmpsave;
  1427.         }
  1428.         break;
  1429.     case C_BLOCK:
  1430.     case C_ELSE:
  1431.     case C_IF:
  1432.         if (cmd->ucmd.ccmd.cc_true)
  1433.         shouldsave |= cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1434.         break;
  1435.     case C_EXPR:
  1436.         if (cmd->ucmd.acmd.ac_expr)
  1437.         shouldsave |= arg_tosave(cmd->ucmd.acmd.ac_expr,willsave);
  1438.         break;
  1439.     }
  1440.     lastcmd = cmd;
  1441.     cmd = cmd->c_next;
  1442.     if (cmd && cmd == head)        /* reached end of while loop */
  1443.         break;
  1444.     }
  1445.     return shouldsave;
  1446. }
  1447.  
  1448.  
  1449. static int
  1450. arg_tosave(arg,willsave)
  1451. register ARG *arg;
  1452. int willsave;
  1453. {
  1454.     register int i;
  1455.     int shouldsave = FALSE;
  1456.  
  1457.  
  1458.     for (i = arg->arg_len; i >= 1; i--) {
  1459.     switch (arg[i].arg_type & A_MASK) {
  1460.     case A_NULL:
  1461.         break;
  1462.     case A_LEXPR:
  1463.     case A_EXPR:
  1464.         shouldsave |= arg_tosave(arg[i].arg_ptr.arg_arg,shouldsave);
  1465.         break;
  1466.     case A_CMD:
  1467.         shouldsave |= cmd_tosave(arg[i].arg_ptr.arg_cmd,shouldsave);
  1468.         break;
  1469.     case A_WORD:
  1470.     case A_STAB:
  1471.     case A_LVAL:
  1472.     case A_READ:
  1473.     case A_GLOB:
  1474.     case A_ARYLEN:
  1475.     case A_SINGLE:
  1476.     case A_DOUBLE:
  1477.     case A_BACKTICK:
  1478.         break;
  1479.     case A_SPAT:
  1480.         shouldsave |= spat_tosave(arg[i].arg_ptr.arg_spat);
  1481.         break;
  1482.     }
  1483.     }
  1484.     switch (arg->arg_type) {
  1485.     case O_RETURN:
  1486.     saw_return = TRUE;
  1487.     break;
  1488.     case O_EVAL:
  1489.     case O_SUBR:
  1490.     shouldsave = TRUE;
  1491.     break;
  1492.     }
  1493.     if (willsave)
  1494.     (void)apush(tosave,arg->arg_ptr.arg_str);
  1495.     return shouldsave;
  1496. }
  1497.  
  1498.  
  1499. static int
  1500. spat_tosave(spat)
  1501. register SPAT *spat;
  1502. {
  1503.     int shouldsave = FALSE;
  1504.  
  1505.  
  1506.     if (spat->spat_runtime)
  1507.     shouldsave |= arg_tosave(spat->spat_runtime,FALSE);
  1508.     if (spat->spat_repl) {
  1509.     shouldsave |= arg_tosave(spat->spat_repl,FALSE);
  1510.     }
  1511.  
  1512.  
  1513.     return shouldsave;
  1514. }
  1515.  
  1516.  
  1517.